package values

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"reflect"
	"slices"
	"strings"
	"sync"
	"time"
	"unsafe"
)

// ToSliceAny 转换any目标为 []any 切片, 如果转换失败, 则返回空的 []any 切片
func ToSliceAny(v any) []any {
	if v == nil {
		return []any{}
	}
	to, _ := ToSliceAnyE(v)
	return to
}

// ToSliceAnyD  转换any目标为 []any 切片, 如果转换失败, 则返回defaultVal指定的默认值
func ToSliceAnyD(v any, defaultVal []any) []any {
	if v == nil {
		return defaultVal
	}
	if to, err := ToSliceAnyE(v); err == nil {
		return to
	}
	return defaultVal
}

// ToSliceAnyE 转换any目标为 []any 切片, 如果转换失败, 则返回空的 []any 切片和错误信息
func ToSliceAnyE(v any) ([]any, error) {
	return _toSliceAnyE(UnderefVal(v))
}

// _toSliceAnyE 尝试将any目标转换为 []any 切片, 如果转换失败, 则返回空的 []any 切片和错误信息
//   - 待转换目标为已经UnderefVal处理的参数
func _toSliceAnyE(v any) ([]any, error) {
	toVal := []any{}
	if v == nil {
		return toVal, errors.New("ToSliceAnyE: nil pointer not support")
	}
	// 通过断言判断是否为 []any / JsonString 类型
	switch vs := v.(type) {
	case []any:
		if len(vs) == 0 {
			return toVal, nil
		}
		return append(toVal, vs...), nil

	case []byte:
		if json.Valid(vs) {
			vsAny := []any{}
			if err := json.Unmarshal(vs, &vsAny); err == nil {
				return vsAny, nil
			} else {
				return toVal, fmt.Errorf("ToSliceAnyE: []byte to []any type, failed unmarshal: %s", err.Error())
			}
		}
		// Like []uint8  After _appendSliceAnyBase to []T
	case string:
		if vs != "" && strings.HasPrefix(vs, "[") && strings.HasSuffix(vs, "]") && json.Valid([]byte(vs)) {
			vsAny := []any{}
			if err := json.Unmarshal([]byte(vs), &vsAny); err == nil {
				return vsAny, nil
			} else {
				return toVal, fmt.Errorf("ToSliceAnyE: string to []any type, failed unmarshal: %s", err.Error())
			}
		}
		return toVal, errors.New("ToSliceAnyE: string to []any type not support")
	case bool,
		int, int8, int16, int32, int64,
		uint, uint8, uint16, uint32, uint64, uintptr,
		float32, float64,
		complex64, complex128,
		time.Time, time.Duration, time.Location, time.Month, time.Weekday, time.Ticker, time.Timer,
		struct{}, chan any, func(), unsafe.Pointer,
		bytes.Buffer, strings.Builder,
		reflect.Type, reflect.Value, reflect.Kind,
		sync.Mutex, sync.RWMutex, sync.Cond, sync.Once, sync.Pool, sync.WaitGroup, sync.Locker,
		error,
		json.Number:
		// 如果待转换值是Golang 常用的基本类型, 则直接返回错误信息
		return toVal, errors.New("ToSliceAnyE: basicType to []T type not support")
	}
	// [1] 通过断言判断待转换值是否为[]TypeBase 类型
	if toVal, err, next := _appendSliceAnyBase(v); !next {
		return toVal, err
	}
	// [2] 通过断言判断待转换值是否为[][]TypeBase 类型
	if toVal, err, next := _appendSliceAnySlice(v); !next {
		return toVal, err
	}
	// [3] 尝试反射检查是否为Slice或Array类型
	return _appendSliceAnyReflect(v)
}
func _appendSliceAny[T any](vs []T) ([]any, error, bool) {
	if vs == nil {
		return []any{}, errors.New("ToSliceAnyE: nil pointer not support"), false // Next "false" To Break
	}
	if len(vs) == 0 {
		return []any{}, nil, false // Next "false" To Break
	}
	toVal := make([]any, len(vs))
	for i, v := range vs {
		toVal[i] = v
	}
	return toVal, nil, false // Next "false" To Break
}

// [1] 通过断言判断待转换值是否为[]TypeBase 类型
func _appendSliceAnyBase(v any) ([]any, error, bool) {
	// v 已经经过UnderefVal处理，不会为指针类型
	switch vs := v.(type) {
	default:
		return []any{}, nil, true // Next "true" To continue
	case []any:
		return slices.Clone(vs), nil, false // Next "false" To Break
	case []string:
		return _appendSliceAny(vs)
	case []*string:
		return _appendSliceAny(vs)
	case []int:
		return _appendSliceAny(vs)
	case []*int:
		return _appendSliceAny(vs)
	case []int8:
		return _appendSliceAny(vs)
	case []*int8:
		return _appendSliceAny(vs)
	case []int16:
		return _appendSliceAny(vs)
	case []*int16:
		return _appendSliceAny(vs)
	case []int32:
		return _appendSliceAny(vs)
	case []*int32:
		return _appendSliceAny(vs)
	case []int64:
		return _appendSliceAny(vs)
	case []*int64:
		return _appendSliceAny(vs)
	case []uint8:
		return _appendSliceAny(vs)
	case []*uint8:
		return _appendSliceAny(vs)
	case []uint16:
		return _appendSliceAny(vs)
	case []*uint16:
		return _appendSliceAny(vs)
	case []uint32:
		return _appendSliceAny(vs)
	case []*uint32:
		return _appendSliceAny(vs)
	case []uint64:
		return _appendSliceAny(vs)
	case []*uint64:
		return _appendSliceAny(vs)
	case []float32:
		return _appendSliceAny(vs)
	case []*float32:
		return _appendSliceAny(vs)
	case []float64:
		return _appendSliceAny(vs)
	case []*float64:
		return _appendSliceAny(vs)
	case []bool:
		return _appendSliceAny(vs)
	case []*bool:
		return _appendSliceAny(vs)
	case []time.Time:
		return _appendSliceAny(vs)
	case []*time.Time:
		return _appendSliceAny(vs)
	case []time.Duration:
		return _appendSliceAny(vs)
	case []*time.Duration:
		return _appendSliceAny(vs)
	case []time.Month:
		return _appendSliceAny(vs)
	case []*time.Month:
		return _appendSliceAny(vs)
	case []time.Weekday:
		return _appendSliceAny(vs)
	case []*time.Weekday:
		return _appendSliceAny(vs)
	case []json.Number:
		return _appendSliceAny(vs)
	case []*json.Number:
		return _appendSliceAny(vs)
	case []error:
		return _appendSliceAny(vs)
	case []*error:
		return _appendSliceAny(vs)
	}
}

// [2] 通过断言判断待转换值是否为[][]TypeBase 类型
func _appendSliceAnySlice(v any) ([]any, error, bool) {
	// v 已经经过UnderefVal处理，不会为指针类型
	switch vs := v.(type) {
	default:
		return []any{}, nil, true // Next "true" To continue
	case [][]any:
		return _appendSliceAny(vs)
	case [][]string:
		return _appendSliceAny(vs)
	case [][]int:
		return _appendSliceAny(vs)
	case [][]int8:
		return _appendSliceAny(vs)
	case [][]int16:
		return _appendSliceAny(vs)
	case [][]int32:
		return _appendSliceAny(vs)
	case [][]int64:
		return _appendSliceAny(vs)
	case [][]uint8:
		return _appendSliceAny(vs)
	case [][]uint16:
		return _appendSliceAny(vs)
	case [][]uint32:
		return _appendSliceAny(vs)
	case [][]uint64:
		return _appendSliceAny(vs)
	case [][]float32:
		return _appendSliceAny(vs)
	case [][]float64:
		return _appendSliceAny(vs)
	case [][]bool:
		return _appendSliceAny(vs)
	case [][]time.Time:
		return _appendSliceAny(vs)
	case [][]time.Duration:
		return _appendSliceAny(vs)
	case [][]time.Month:
		return _appendSliceAny(vs)
	case [][]time.Weekday:
		return _appendSliceAny(vs)
	case [][]json.Number:
		return _appendSliceAny(vs)
	case [][]error:
		return _appendSliceAny(vs)
	}
}

// [3] 尝试反射检查是否为Slice或Array类型
func _appendSliceAnyReflect(v any) ([]any, error) {
	// 获取输入值的反射类型和值
	// v 已经经过UnderefVal处理，不会为指针类型
	vType := reflect.TypeOf(v)
	vValue := reflect.ValueOf(v)
	// 检查是否为切片或数组类型
	if vType.Kind() != reflect.Slice && vType.Kind() != reflect.Array {
		return []any{}, fmt.Errorf("ToSliceAnyE: unsupported type %T, expected slice or array", v)
	}
	// 如果长度为0，直接返回空切片
	if vValue.Len() == 0 {
		return []any{}, nil
	}
	// 将Slice或Array转换为[]any类型
	vsAny := make([]any, 0, vValue.Len())
	for i := range vValue.Len() {
		vsAny = append(vsAny, vValue.Index(i).Interface())
	}
	return vsAny, nil
}
